package com.small.nacos.naming.healthcheck;

import com.alibaba.nacos.api.exception.NacosException;
import com.small.nacos.naming.consistency.KeyBuilder;
import com.small.nacos.naming.core.DistroMapper;
import com.small.nacos.naming.core.Instance;
import com.small.nacos.naming.core.Service;
import com.small.nacos.naming.core.ServiceManager;
import com.small.nacos.naming.core.utils.ApplicationUtils;
import com.small.nacos.naming.push.PushService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;

/**
 * @Author zhoujin
 * @Date 2022/7/23 12:29
 */
public class ClientBeatCheckTask implements Runnable {

    private final static Logger LOGGER = LoggerFactory.getLogger(ClientBeatCheckTask.class);

    private Service service;

    public ClientBeatCheckTask(Service service) {
        this.service = service;
    }

    @Override
    public void run() {

        // distro 如果当前节点不负责这个service，不处理
        if (!getDistroMapper().responsible(service.getName())) {
            return;
        }
        getPushService().serviceChanged(service);
        try {
            List<Instance> instances = service.allIPs(true);
            for (Instance instance : instances) {
                if (System.currentTimeMillis() - instance.getLastBeat() > instance.getInstanceHeartBeatTimeOut()) {
                    if (instance.isHealthy()) {
                        instance.setHealthy(false);
                        //getPushService().serviceChanged(service);
                    }
                }

                if (System.currentTimeMillis() - instance.getLastBeat() > instance.getIpDeleteTimeout()) {
                    deleteIp(instance);
                }
            }
        } catch (Exception e) {
            LOGGER.warn("Exception while processing client beat time out.", e);
        }
    }

    private void deleteIp(Instance instance) throws NacosException {
        ServiceManager serviceManager = ApplicationUtils.getBean(ServiceManager.class);
        serviceManager.removeInstance(service.getNamespaceId(), service.getName(), instance.isEphemeral(), instance);
    }

    public String taskKey() {
        return KeyBuilder.buildServiceMetaKey(service.getNamespaceId(), service.getName());
    }

    public PushService getPushService() {
        return ApplicationUtils.getBean(PushService.class);
    }

    public DistroMapper getDistroMapper() {
        return ApplicationUtils.getBean(DistroMapper.class);
    }
}
